import { configService, type AttackChainConfig } from './configService'
import { attackChainService, type AttackChainCsvData } from './attackChainService'

// 攻击链数据类型定义
export interface AttackChainData {
  nodes: Array<{
    id: number
    name: string
    backends: number
    frontendIp?: string
    backendIps?: string[]
    level?: number
  }>
  connections: Array<{
    from: { nodeId: number | 'target'; kind: 'frontend' | 'backend' | 'target'; backendIndex?: number }
    to: { nodeId: number | 'target'; kind: 'frontend' | 'backend' | 'target'; backendIndex?: number }
  }>
  targetNode?: {
    ip: string
    port: number
  }
  victimType?: 'dns' | 'non-dns'
  environment?: 'testbed' | 'realnet'  // 环境类型：测试床或实网
  selfExcitation?: boolean  // 自激选项（仅在测试床模式下使用）
  timestamp: string
  attackId: string
}

export interface AttackResponse {
  success: boolean
  message: string
  attackId?: string
  data?: any
}

class AttackDataService {
  private config: AttackChainConfig | null = null

  /**
   * 初始化服务
   */
  async init() {
    this.config = await configService.getAttackChainConfig()
  }

  /**
   * 发送攻击链数据到目标端口
   * @param attackData 攻击链数据
   * @returns Promise<AttackResponse>
   */
  async sendAttackChainData(attackData: AttackChainData): Promise<AttackResponse> {
    if (!this.config) {
      await this.init()
    }

    // 转换为CSV格式
    const csvData = attackChainService.convertTopologyToAttackChain(
      attackData.nodes,
      attackData.connections,
      attackData.targetNode
    )

    // 验证数据
    const validation = attackChainService.validateAttackData(csvData)
    if (!validation.valid) {
      throw new Error(`数据验证失败: ${validation.errors.join(', ')}`)
    }

    const url = await configService.getSendAttackDataUrl()
    
    try {
      console.log('发送攻击链数据到:', url)
      console.log('攻击链CSV数据:', csvData)

      // 生成CSV字符串
      const csvString = attackChainService.generateCsvString(csvData)
      console.log('发送的CSV内容:', csvString)

      // 构建JSON格式的请求数据，包含CSV数据、攻击类型、攻击目标IP和环境类型
      const requestData: any = {
        csv_data: csvString,  // CSV数据作为字符串
        victim_type: attackData.victimType || 'dns',  // 攻击类型，默认为dns
        target_ip: attackData.targetNode?.ip || '',  // 攻击目标IP
        environment: attackData.environment || 'testbed',  // 环境类型，默认为测试床
        timestamp: attackData.timestamp,
        attack_id: csvData.attackId
      }
      
      // 仅在测试床模式下添加自激参数
      if (attackData.environment === 'testbed' && attackData.selfExcitation !== undefined) {
        requestData.self_excitation = attackData.selfExcitation
      }

      console.log('发送的JSON请求数据:', requestData)

      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json, text/plain'
        },
        body: JSON.stringify(requestData),
        signal: this.createTimeoutSignal(this.config!.timeout)
      })

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`)
      }

      // 尝试解析JSON响应，如果失败则读取文本
      let responseData: any
      try {
        responseData = await response.json()
      } catch {
        const responseText = await response.text()
        responseData = { response: responseText }
      }
      console.log('攻击数据发送成功:', responseData)


      return {
        success: true,
        message: '攻击链数据发送成功',
        attackId: csvData.attackId,
        data: { 
          response: responseData,
          csvData: csvData,
          rowCount: csvData.rows.length
        }
      }
    } catch (error) {
      console.error('发送攻击链数据失败:', error)
      
      // 重试逻辑
      return await this.retrySendAttackData(attackData, 1)
    }
  }

  /**
   * 重试发送攻击数据
   * @param attackData 攻击链数据
   * @param attempt 当前尝试次数
   * @returns Promise<AttackResponse>
   */
  private async retrySendAttackData(attackData: AttackChainData, attempt: number): Promise<AttackResponse> {
    if (attempt > this.config!.retryCount) {
      return {
        success: false,
        message: `发送失败，已重试 ${this.config!.retryCount} 次`
      }
    }

    console.log(`重试发送攻击数据，第 ${attempt} 次尝试`)
    
    // 等待一段时间后重试
    await new Promise(resolve => setTimeout(resolve, 1000 * attempt))

    try {
      // 转换为CSV格式
      const csvData = attackChainService.convertTopologyToAttackChain(
        attackData.nodes,
        attackData.connections,
        attackData.targetNode
      )

      const url = await configService.getSendAttackDataUrl()
      const csvString = attackChainService.generateCsvString(csvData)
      
      // 构建JSON格式的请求数据，包含CSV数据、攻击类型、攻击目标IP和环境类型
      const requestData: any = {
        csv_data: csvString,  // CSV数据作为字符串
        victim_type: attackData.victimType || 'dns',  // 攻击类型，默认为dns
        target_ip: attackData.targetNode?.ip || '',  // 攻击目标IP
        environment: attackData.environment || 'testbed',  // 环境类型，默认为测试床
        timestamp: attackData.timestamp,
        attack_id: csvData.attackId
      }
      
      // 仅在测试床模式下添加自激参数
      if (attackData.environment === 'testbed' && attackData.selfExcitation !== undefined) {
        requestData.self_excitation = attackData.selfExcitation
      }

      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json, text/plain'
        },
        body: JSON.stringify(requestData),
        signal: this.createTimeoutSignal(this.config!.timeout)
      })

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`)
      }

      // 尝试解析JSON响应，如果失败则读取文本
      let responseData: any
      try {
        responseData = await response.json()
      } catch {
        const responseText = await response.text()
        responseData = { response: responseText }
      }
      console.log('重试发送成功:', responseData)


      return {
        success: true,
        message: `攻击链数据发送成功（第 ${attempt} 次重试）`,
        attackId: csvData.attackId,
        data: { 
          response: responseData,
          csvData: csvData,
          rowCount: csvData.rows.length
        }
      }
    } catch (error) {
      console.error(`第 ${attempt} 次重试失败:`, error)
      return await this.retrySendAttackData(attackData, attempt + 1)
    }
  }

  /**
   * 获取攻击状态
   * @param attackId 攻击ID
   * @returns Promise<any>
   */
  async getAttackStatus(attackId: string): Promise<any> {
    if (!this.config) {
      await this.init()
    }

    const baseUrl = await configService.getTargetUrl()
    const url = `${baseUrl}${this.config!.endpoints.getStatus}?attackId=${attackId}`

    try {
      const response = await fetch(url, {
        method: 'GET',
        headers: {
          'Accept': 'application/json'
        },
        signal: this.createTimeoutSignal(this.config!.timeout)
      })

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`)
      }

      // 尝试解析JSON，如果失败则返回文本
      try {
        return await response.json()
      } catch (jsonError) {
        const textResponse = await response.text()
        return { response: textResponse }
      }
    } catch (error) {
      console.error('获取攻击状态失败:', error)
      throw error
    }
  }

  /**
   * 创建超时信号
   * @param timeout 超时时间(毫秒)
   * @returns AbortSignal
   */
  private createTimeoutSignal(timeout: number): AbortSignal {
    const controller = new AbortController()
    setTimeout(() => {
      controller.abort()
    }, timeout)
    return controller.signal
  }

  /**
   * 生成攻击ID
   * @returns string
   */
  generateAttackId(): string {
    return `attack_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }
}

// 导出单例实例
export const attackDataService = new AttackDataService()
